home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / game / wins1726.zip / LSYS.C < prev    next >
C/C++ Source or Header  |  1992-02-01  |  22KB  |  879 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #ifdef __TURBOC__
  6. #include <alloc.h>
  7. #else
  8. #include <malloc.h>
  9. #endif
  10. #include "fractint.h"
  11. #define size    ssize
  12. /* Needed for use of asm -- helps decide which pointer to function
  13.  * to put into the struct lsys_cmds.
  14.  */
  15. extern int cpu;
  16. extern int fpu;
  17. extern int debugflag;
  18. extern int xdots,ydots;
  19. extern int colors;
  20. extern char LFileName[];
  21. extern char LName[];
  22. extern double param[];
  23. extern int overflow;
  24.  
  25. int Lsystem();
  26. extern int thinking(int,char *);
  27.  
  28. struct lsys_cmd {
  29.   char ch;
  30.   void (*f)(long n);
  31.   long n;
  32. };
  33.  
  34. static double      _fastcall getnumber(char far **);
  35. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_cmd far **,int);
  36. static int      _fastcall findscale(struct lsys_cmd far *, struct lsys_cmd far **, int);
  37. static struct lsys_cmd far * _fastcall drawLSys(struct lsys_cmd far *, struct lsys_cmd far **, int);
  38. static int      _fastcall readLSystemFile(char *);
  39. static void      _fastcall free_rules_mem(void);
  40. static int      _fastcall save_rule(char *,char far **);
  41. static struct lsys_cmd far *SizeTransform(char far *s);
  42. static struct lsys_cmd far *DrawTransform(char far *s);
  43. static void free_lcmds();
  44.  
  45. static long aspect; /* aspect ratio of each pixel, ysize/xsize */
  46.  
  47. /* Some notes to Adrian from PB, made when I integrated with v15:
  48.      printfs changed to work with new user interface
  49.      bug at end of readLSystemFile, the line which said rulind=0 fixed
  50.        to say *rulind=0
  51.      the calloc was not worthwhile, it was just for a 54 byte area, cheaper
  52.        to keep it as a static;    but there was a static 201 char buffer I
  53.        changed to not be static
  54.      use of strdup was a nono, caused problems running out of space cause
  55.        the memory allocated each time was never freed; I've changed to
  56.        use far memory and to free when done
  57.    */
  58.  
  59. long sins[50];
  60. long coss[50];
  61. /* dmaxangle is maxangle - 1. */
  62. char maxangle,dmaxangle,curcolor;
  63. long size;
  64. unsigned long realangle;
  65. long xpos,ypos;
  66. char counter,angle,reverse,stackoflow;
  67. long lsys_Xmin, lsys_Xmax, lsys_Ymin, lsys_Ymax;
  68.  
  69. /* Macro to take an FP number and turn it into a
  70.  * 16/16-bit fixed-point number.
  71.  */
  72. #define FIXEDMUL    524288L
  73. #define FIXEDPT(x)    ((long) (FIXEDMUL * (x)))
  74.  
  75. /* The number by which to multiply sines, cosines and other
  76.  * values with magnitudes less than or equal to 1.
  77.  * sins and coss are a 3/29 bit fixed-point scheme (so the
  78.  * range is +/- 2, with good accuracy.    The range is to
  79.  * avoid overflowing when the aspect ratio is taken into
  80.  * account.
  81.  */
  82. #define FIXEDLT1    536870912.0
  83.  
  84. /* Multiply by this number to convert an unsigned 32-bit long
  85.  * to an angle from 0-2PI.
  86.  */
  87. #define ANGLE2DOUBLE    (2*PI / 4294967296.)
  88.  
  89. static int ispow2(long n)
  90. {
  91.   return (n == (n & -n));
  92. }
  93.  
  94. extern void lsys_doplus(long n);
  95.  
  96. #if 0
  97. static void lsys_doplus(long n)
  98. {
  99.   if (reverse) {
  100.     if (++angle == maxangle)
  101.       angle = 0;
  102.   }
  103.   else {
  104.     if (angle)
  105.       angle--;
  106.     else
  107.       angle = dmaxangle;
  108.   }
  109. }
  110. #endif
  111.  
  112. extern void lsys_doplus_pow2(long n);
  113. #if 0
  114. /* This is the same as lsys_doplus, except maxangle is a power of 2. */
  115. static void lsys_doplus_pow2(long n)
  116. {
  117.   if (reverse) {
  118.     angle++;
  119.     angle &= dmaxangle;
  120.   }
  121.   else {
  122.     angle--;
  123.     angle &= dmaxangle;
  124.   }
  125. }
  126. #endif
  127.  
  128. extern void lsys_dominus(long n);
  129. #if 0
  130. static void lsys_dominus(long n)
  131. {
  132.   if (reverse) {
  133.     if (angle)
  134.       angle--;
  135.     else
  136.       angle = dmaxangle;
  137.   }
  138.   else {
  139.     if (++angle == maxangle)
  140.       angle = 0;
  141.   }
  142. }
  143. #endif
  144.  
  145. extern void lsys_dominus_pow2(long n);
  146. #if 0
  147. static void lsys_dominus_pow2(long n)
  148. {
  149.   if (reverse) {
  150.     angle--;
  151.     angle &= dmaxangle;
  152.   }
  153.   else {
  154.     angle++;
  155.     angle &= dmaxangle;
  156.   }
  157. }
  158. #endif
  159.  
  160. static void lsys_doslash(long n)
  161. {
  162.   if (reverse)
  163.     realangle -= n;
  164.   else
  165.     realangle += n;
  166. }
  167. extern void lsys_doslash_386(long n);
  168.  
  169. static void lsys_dobslash(long n)
  170. {
  171.   if (reverse)
  172.     realangle += n;
  173.   else
  174.     realangle -= n;
  175. }
  176. extern void lsys_dobslash_386(long n);
  177.  
  178. static void lsys_doat(long n)
  179. {
  180.   size = multiply(size, n, 19);
  181. }
  182. extern void lsys_doat_386(long n);
  183.  
  184. static void lsys_dopipe(long n)
  185. {
  186.   angle += maxangle / 2;
  187.   angle %= maxangle;
  188. }
  189.  
  190. extern void lsys_dopipe_pow2(long n);
  191.  
  192. #if 0
  193. static void lsys_dopipe_pow2(long n)
  194. {
  195.   angle += maxangle >> 1;
  196.   angle &= dmaxangle;
  197. }
  198. #endif
  199.  
  200. extern void lsys_dobang(long n);
  201. #if 0
  202. static void lsys_dobang(long n)
  203. {
  204.   reverse = ! reverse;
  205. }
  206. #endif
  207.  
  208. static void lsys_dosizedm(long n)
  209. {
  210.   double angle = (double) realangle * ANGLE2DOUBLE;
  211.   double s, c;
  212.   long fixedsin, fixedcos;
  213.   FPUsincos(&angle, &s, &c);
  214.   fixedsin = (long) (s * FIXEDLT1);
  215.   fixedcos = (long) (c * FIXEDLT1);
  216.  
  217.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  218.   ypos += multiply(size, fixedsin, 29);
  219.  
  220. //xpos+=size*aspect*cos(realangle*PI/180);
  221. //ypos+=size*sin(realangle*PI/180);
  222.   if (xpos>lsys_Xmax) lsys_Xmax=xpos;
  223.   if (ypos>lsys_Ymax) lsys_Ymax=ypos;
  224.   if (xpos<lsys_Xmin) lsys_Xmin=xpos;
  225.   if (ypos<lsys_Ymin) lsys_Ymin=ypos;
  226. }
  227.  
  228. static void lsys_dosizegf(long n)
  229. {
  230.   xpos += multiply(size, (long) coss[angle], 29);
  231.   ypos += multiply(size, (long) sins[angle], 29);
  232. //xpos+=size*coss[angle];
  233. //ypos+=size*sins[angle];
  234.   if (xpos>lsys_Xmax) lsys_Xmax=xpos;
  235.   if (ypos>lsys_Ymax) lsys_Ymax=ypos;
  236.   if (xpos<lsys_Xmin) lsys_Xmin=xpos;
  237.   if (ypos<lsys_Ymin) lsys_Ymin=ypos;
  238. }
  239. extern void lsys_dosizegf_386(long n);
  240.  
  241. static void lsys_dodrawd(long n)
  242. {
  243.   double angle = (double) realangle * ANGLE2DOUBLE;
  244.   double s, c;
  245.   long fixedsin, fixedcos;
  246.   int lastx, lasty;
  247.   FPUsincos(&angle, &s, &c);
  248.   fixedsin = (long) (s * FIXEDLT1);
  249.   fixedcos = (long) (c * FIXEDLT1);
  250.  
  251.   lastx=(int) (xpos >> 19);
  252.   lasty=(int) (ypos >> 19);
  253.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  254.   ypos += multiply(size, fixedsin, 29);
  255. //xpos+=size*aspect*cos(realangle*PI/180);
  256. //ypos+=size*sin(realangle*PI/180);
  257.   draw_line(lastx,lasty,(int)(xpos >> 19),(int)(ypos>>19),curcolor);
  258. }
  259.  
  260. static void lsys_dodrawm(long n)
  261. {
  262.   double angle = (double) realangle * ANGLE2DOUBLE;
  263.   double s, c;
  264.   long fixedsin, fixedcos;
  265.   FPUsincos(&angle, &s, &c);
  266.   fixedsin = (long) (s * FIXEDLT1);
  267.   fixedcos = (long) (c * FIXEDLT1);
  268.  
  269. //xpos+=size*aspect*cos(realangle*PI/180);
  270. //ypos+=size*sin(realangle*PI/180);
  271.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  272.   ypos += multiply(size, fixedsin, 29);
  273. }
  274.  
  275. static void lsys_dodrawg(long n)
  276. {
  277.   xpos += multiply(size, (long) coss[angle], 29);
  278.   ypos += multiply(size, (long) sins[angle], 29);
  279. //xpos+=size*coss[angle];
  280. //ypos+=size*sins[angle];
  281. }
  282. extern void lsys_dodrawg_386(long n);
  283.  
  284. static void lsys_dodrawf(long n)
  285. {
  286.   int lastx = (int) (xpos >> 19);
  287.   int lasty = (int) (ypos >> 19);
  288.   xpos += multiply(size, (long) coss[angle], 29);
  289.   ypos += multiply(size, (long) sins[angle], 29);
  290. //xpos+=size*coss[angle];
  291. //ypos+=size*sins[angle];
  292.   draw_line(lastx,lasty,(int)(xpos>>19),(int)(ypos>>19),curcolor);
  293. }
  294.  
  295. static void lsys_dodrawc(long n)
  296. {
  297.   curcolor = ((int) n) % colors;
  298. }
  299.  
  300. static void lsys_dodrawgt(long n)
  301. {
  302.   curcolor -= n;
  303.   if ((curcolor &= colors-1) == 0)
  304.     curcolor = colors-1;
  305. }
  306.  
  307. static void lsys_dodrawlt(long n)
  308. {
  309.   curcolor += n;
  310.   if ((curcolor &= colors-1) == 0)
  311.     curcolor = 1;
  312. }
  313.  
  314. static double _fastcall getnumber(char far **str)
  315. {
  316.    char numstr[30];
  317.    float ret;
  318.    int i,root,inverse;
  319.  
  320.    root=0;
  321.    inverse=0;
  322.    strcpy(numstr,"");
  323.    (*str)++;
  324.    switch (**str)
  325.    {
  326.    case 'q':
  327.       root=1;
  328.       (*str)++;
  329.       break;
  330.    case 'i':
  331.       inverse=1;
  332.       (*str)++;
  333.       break;
  334.    }
  335.    switch (**str)
  336.    {
  337.    case 'q':
  338.       root=1;
  339.       (*str)++;
  340.       break;
  341.    case 'i':
  342.       inverse=1;
  343.       (*str)++;
  344.       break;
  345.    }
  346.    i=0;
  347.    while (**str<='9' && **str>='0' || **str=='.')
  348.    {
  349.       numstr[i++]=**str;
  350.       (*str)++;
  351.    }
  352.    (*str)--;
  353.    numstr[i]=0;
  354.    ret=atof(numstr);
  355.    if (root)
  356.      ret=sqrt(ret);
  357.    if (inverse)
  358.      ret = 1/ret;
  359.    return ret;
  360. }
  361.  
  362. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *command, struct lsys_cmd far **rules, int depth)
  363. {
  364.    struct lsys_cmd far **rulind;
  365.    int tran;
  366.  
  367. if (overflow)     /* integer math routines overflowed */
  368.     return NULL;
  369.  
  370. #ifndef __TURBOC__
  371.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  372.       stackoflow = 1;
  373.       return NULL;
  374.       }
  375. #endif
  376.  
  377.    while (command->ch && command->ch !=']') {
  378.       if (! (counter++)) {
  379.      /* let user know we're not dead */
  380.      if (thinking(1,"L-System thinking (higher orders take longer)")) {
  381.         counter--;
  382.         return NULL;
  383.      }
  384.       }
  385.       tran=0;
  386.       if (depth) {
  387.      for(rulind=rules;*rulind;rulind++)
  388.         if ((*rulind)->ch==command->ch) {
  389.            tran=1;
  390.            if (findsize((*rulind)+1,rules,depth-1) == NULL)
  391.           return(NULL);
  392.         }
  393.       }
  394.       if (!depth || !tran) {
  395.     if (command->f)
  396.       (*command->f)(command->n);
  397.     else if (command->ch == '[') {
  398.       char saveang,saverev;
  399.       long savesize,savex,savey;
  400.       unsigned long saverang;
  401.  
  402.       saveang=angle;
  403.       saverev=reverse;
  404.       savesize=size;
  405.       saverang=realangle;
  406.       savex=xpos;
  407.       savey=ypos;
  408.       if ((command=findsize(command+1,rules,depth)) == NULL)
  409.          return(NULL);
  410.       angle=saveang;
  411.       reverse=saverev;
  412.       size=savesize;
  413.       realangle=saverang;
  414.       xpos=savex;
  415.       ypos=savey;
  416.     }
  417.       }
  418.       command++;
  419.    }
  420.    return command;
  421. }
  422.  
  423. static int _fastcall findscale(struct lsys_cmd far *command, struct lsys_cmd far **rules, int depth)
  424. {
  425.    float horiz,vert;
  426.    double xmin, xmax, ymin, ymax;
  427.    double locsize;
  428.    double locaspect;
  429.    int i;
  430.    struct lsys_cmd far *fsret;
  431.    locaspect=SCREENASPECT*xdots/ydots;
  432.    aspect = FIXEDPT(locaspect);
  433.    for(i=0;i<maxangle;i++) {
  434.       sins[i]=(long) ((sin(2*i*PI/maxangle)) * FIXEDLT1);
  435.       coss[i]=(long) ((locaspect * cos(2*i*PI/maxangle)) * FIXEDLT1);
  436.    }
  437.    xpos=ypos=lsys_Xmin=lsys_Xmax=lsys_Ymax=lsys_Ymin=angle=reverse=realangle=counter=0;
  438.    size=FIXEDPT(1);
  439.    fsret = findsize(command,rules,depth);
  440.    thinking(0, NULL); /* erase thinking message if any */
  441.    xmin = (double) lsys_Xmin / FIXEDMUL;
  442.    xmax = (double) lsys_Xmax / FIXEDMUL;
  443.    ymin = (double) lsys_Ymin / FIXEDMUL;
  444.    ymax = (double) lsys_Ymax / FIXEDMUL;
  445.    locsize = (double) size / FIXEDMUL;
  446.    if (fsret == NULL)
  447.       return 0;
  448.    if (xmax == xmin)
  449.       horiz = 1E37;
  450.    else
  451.       horiz = (xdots-10)/(xmax-xmin);
  452.    if (ymax == ymin)
  453.       vert = 1E37;
  454.    else
  455.       vert = (ydots-6) /(ymax-ymin);
  456.    locsize = (vert<horiz) ? vert : horiz;
  457.  
  458.    if (horiz == 1E37)
  459.       xpos = FIXEDPT(xdots/2);
  460.    else
  461.       xpos = FIXEDPT(-xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2);
  462.    if (vert == 1E37)
  463.       ypos = FIXEDPT(ydots/2);
  464.    else
  465.       ypos = FIXEDPT(-ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2);
  466.    size = FIXEDPT(locsize);
  467.    return 1;
  468. }
  469.  
  470. static struct lsys_cmd far * _fastcall drawLSys(struct lsys_cmd far *command,struct lsys_cmd far **rules,int depth)
  471. {
  472.    struct lsys_cmd far **rulind;
  473.    int tran;
  474.  
  475. if (overflow)     /* integer math routines overflowed */
  476.     return NULL;
  477.  
  478. #ifndef __TURBOC__
  479.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  480.       stackoflow = 1;
  481.       return NULL;
  482.       }
  483. #endif
  484.  
  485.    while (command->ch && command->ch !=']') {
  486.       if (!(counter++)) {
  487.      if (check_key()) {
  488.         counter--;
  489.         return NULL;
  490.      }
  491.       }
  492.       tran=0;
  493.       if (depth) {
  494.      for(rulind=rules;*rulind;rulind++)
  495.         if ((*rulind)->ch == command->ch) {
  496.            tran=1;
  497.            if (drawLSys((*rulind)+1,rules,depth-1) == NULL)
  498.           return NULL;
  499.         }
  500.       }
  501.       if (!depth||!tran) {
  502.     if (command->f)
  503.       (*command->f)(command->n);
  504.     else if (command->ch == '[') {
  505.       char saveang,saverev,savecolor;
  506.       long savesize,savex,savey;
  507.       unsigned long saverang;
  508.  
  509.       saveang=angle;
  510.       saverev=reverse;
  511.       savesize=size;
  512.       saverang=realangle;
  513.       savex=xpos;
  514.       savey=ypos;
  515.       savecolor=curcolor;
  516.       if ((command=drawLSys(command+1,rules,depth)) == NULL)
  517.          return(NULL);
  518.       angle=saveang;
  519.       reverse=saverev;
  520.       size=savesize;
  521.       realangle=saverang;
  522.       xpos=savex;
  523.       ypos=savey;
  524.       curcolor=savecolor;
  525.     }
  526.       }
  527.       command++;
  528.    }
  529.    return command;
  530. }
  531.  
  532. #define MAXRULES 27 /* this limits rules to 25 */
  533. static char far *ruleptrs[MAXRULES];
  534. static struct lsys_cmd far *rules2[MAXRULES];
  535.  
  536. static int _fastcall readLSystemFile(char *str)
  537. {
  538.    int c;
  539.    char far **rulind;
  540.    int err=0;
  541.    int linenum,check=0;
  542.    char inline[161],fixed[161],*word;
  543.    FILE *infile;
  544.    char msgbuf[481]; /* enough for 6 full lines */
  545.  
  546.    if (find_file_item(LFileName,str,&infile) < 0)
  547.       return -1;
  548.    while ((c = fgetc(infile)) != '{')
  549.       if (c == EOF) return -1;
  550.  
  551.    maxangle=0;
  552.    for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
  553.    rulind=&ruleptrs[1];
  554.    msgbuf[0]=linenum=0;
  555.  
  556.    while(fgets(inline,160,infile))  /* Max line length 160 chars */
  557.    {
  558.       linenum++;
  559.       if ((word = strchr(inline,';'))) /* strip comment */
  560.      *word = 0;
  561.       strlwr(inline);
  562.  
  563.       if (strspn(inline," \t\n") < strlen(inline)) /* not a blank line */
  564.       {
  565.      word=strtok(inline," =\t\n");
  566.      if (!strcmp(word,"axiom"))
  567.      {
  568.         save_rule(strtok(NULL," \t\n"),&ruleptrs[0]);
  569.         check=1;
  570.      }
  571.      else if (!strcmp(word,"angle"))
  572.      {
  573.         maxangle=atoi(strtok(NULL," \t\n"));
  574.         dmaxangle = maxangle - 1;
  575.         check=1;
  576.      }
  577.      else if (!strcmp(word,"}"))
  578.         break;
  579.      else if (strlen(word)==1)
  580.      {
  581.         strcat(strcpy(fixed,word),strtok(NULL," \t\n"));
  582.         save_rule(fixed,rulind++);
  583.         check=1;
  584.      }
  585.      else
  586.         if (err<6)
  587.         {
  588.            sprintf(&msgbuf[strlen(msgbuf)],
  589.                "Syntax error line %d: %s\n",linenum,word);
  590.            ++err;
  591.         }
  592.      if (check)
  593.      {
  594.         check=0;
  595.         if(word=strtok(NULL," \t\n"))
  596.            if (err<6)
  597.            {
  598.           sprintf(&msgbuf[strlen(msgbuf)],
  599.              "Extra text after command line %d: %s\n",linenum,word);
  600.           ++err;
  601.            }
  602.      }
  603.       }
  604.    }
  605.    fclose(infile);
  606.    if (!ruleptrs[0] && err<6)
  607.    {
  608.       strcat(msgbuf,"Error:  no axiom\n");
  609.       ++err;
  610.    }
  611.    if ((maxangle<3||maxangle>50) && err<6)
  612.    {
  613.       strcat(msgbuf,"Error:  illegal or missing angle\n");
  614.       ++err;
  615.    }
  616.    if (err)
  617.    {
  618.       msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
  619.       stopmsg(0,msgbuf);
  620.       return -1;
  621.    }
  622.    *rulind=NULL;
  623.    return 0;
  624. }
  625.  
  626. static char loaded=0;
  627.  
  628. int Lsystem()
  629. {
  630.    int order;
  631.    char far **rulesc;
  632.    struct lsys_cmd far **sc;
  633.  
  634.    if ( (!loaded) && LLoad())
  635.      return -1;
  636.  
  637.    overflow = 0;        /* reset integer math overflow flag */
  638.  
  639.    order=param[0];
  640.    if (order<=0)
  641.      order=0;
  642.    stackoflow = 0;
  643.  
  644.    sc = rules2;
  645.    for (rulesc = ruleptrs; *rulesc; rulesc++)
  646.      *sc++ = SizeTransform(*rulesc);
  647.    *sc = NULL;
  648.  
  649.    if (findscale(rules2[0], &rules2[1], order)) {
  650.       realangle = angle = reverse = 0;
  651.  
  652.       free_lcmds();
  653.       sc = rules2;
  654.       for (rulesc = ruleptrs; *rulesc; rulesc++)
  655.     *sc++ = DrawTransform(*rulesc);
  656.       *sc = NULL;
  657.  
  658.       /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  659.       if ((curcolor=15) > colors) curcolor=colors-1;
  660.       drawLSys(rules2[0], &rules2[1], order);
  661.    }
  662.    if (stackoflow)
  663.    {
  664.       static char far msg[]={"insufficient memory, try a lower order"};
  665.       stopmsg(0,msg);
  666.    }
  667.    if (overflow) {
  668.       static char far msg[]={"Integer math routines failed, try a lower order"};
  669.       stopmsg(0,msg);
  670.       }
  671.    free_rules_mem();
  672.    free_lcmds();
  673.    loaded=0;
  674.    return 0;
  675. }
  676.  
  677. int LLoad()
  678. {
  679.    char i;
  680.    if (readLSystemFile(LName)) { /* error occurred */
  681.       free_rules_mem();
  682.       loaded=0;
  683.       return -1;
  684.    }
  685.    for(i=0;i<maxangle;i++) {
  686.       sins[i]=(long) ((sin(2*i*PI/maxangle)) * FIXEDLT1);
  687.       coss[i]=(long) (((double) aspect / (double) FIXEDMUL * cos(2*i*PI/maxangle)) * FIXEDLT1);
  688.    }
  689.    loaded=1;
  690.    return 0;
  691. }
  692.  
  693. static void _fastcall free_rules_mem()
  694. {
  695.    int i;
  696.    for(i=0;i<MAXRULES;++i)
  697.       if(ruleptrs[i]) farmemfree(ruleptrs[i]);
  698. }
  699.  
  700. static int _fastcall save_rule(char *rule,char far **saveptr)
  701. {
  702.    int i;
  703.    char far *tmpfar;
  704.    i=strlen(rule)+1;
  705.    if((tmpfar=farmemalloc((long)i))==NULL) {
  706.        stackoflow = 1;
  707.        return -1;
  708.        }
  709.    *saveptr=tmpfar;
  710.    while(--i>=0) *(tmpfar++)=*(rule++);
  711.    return 0;
  712. }
  713.  
  714. static struct lsys_cmd far *SizeTransform(char far *s)
  715. {
  716.   struct lsys_cmd far *ret;
  717.   struct lsys_cmd far *doub;
  718.   int max = 10;
  719.   int n = 0;
  720.   void (*f)(long);
  721.   long num;
  722.  
  723.   void (*plus)(long) = (ispow2(maxangle)) ? lsys_doplus_pow2 : lsys_doplus;
  724.   void (*minus)(long) = (ispow2(maxangle)) ? lsys_dominus_pow2 : lsys_dominus;
  725.   void (*pipe)(long) = (ispow2(maxangle)) ? lsys_dopipe_pow2 : lsys_dopipe;
  726.  
  727.   void (*slash)(long) =  (cpu == 386) ? lsys_doslash_386 : lsys_doslash;
  728.   void (*bslash)(long) = (cpu == 386) ? lsys_dobslash_386 : lsys_dobslash;
  729.   void (*at)(long) =     (cpu == 386) ? lsys_doat_386 : lsys_doat;
  730.   void (*dogf)(long) =   (cpu == 386) ? lsys_dosizegf_386 : lsys_dosizegf;
  731.  
  732.   ret = (struct lsys_cmd far *) farmemalloc((long) max * sizeof(struct lsys_cmd));
  733.   if (ret == NULL) {
  734.        stackoflow = 1;
  735.        return NULL;
  736.        }
  737.   while (*s) {
  738.     f = NULL;
  739.     num = 0;
  740.     ret[n].ch = *s;
  741.     switch (*s) {
  742.       case '+': f = plus;            break;
  743.       case '-': f = minus;           break;
  744.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  745.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  746.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  747.       case '|': f = pipe;            break;
  748.       case '!': f = lsys_dobang;     break;
  749.       case 'd':
  750.       case 'm': f = lsys_dosizedm;   break;
  751.       case 'g':
  752.       case 'f': f = dogf;       break;
  753.       case '[': num = 1;        break;
  754.       case ']': num = 2;        break;
  755.       default:
  756.     num = 3;
  757.     break;
  758.     }
  759.     ret[n].f = f;
  760.     ret[n].n = num;
  761.     if (++n == max) {
  762.       doub = (struct lsys_cmd far *) farmemalloc((long) max*2*sizeof(struct lsys_cmd));
  763.       if (doub == NULL) {
  764.          farmemfree(ret);
  765.          stackoflow = 1;
  766.          return NULL;
  767.          }
  768.       far_memcpy(doub, ret, max*sizeof(struct lsys_cmd));
  769.       farmemfree(ret);
  770.       ret = doub;
  771.       max <<= 1;
  772.     }
  773.     s++;
  774.   }
  775.   ret[n].ch = 0;
  776.   ret[n].f = NULL;
  777.   ret[n].n = 0;
  778.   n++;
  779.  
  780.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  781.   if (doub == NULL) {
  782.        farmemfree(ret);
  783.        stackoflow = 1;
  784.        return NULL;
  785.        }
  786.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  787.   farmemfree(ret);
  788.   return doub;
  789. }
  790.  
  791. static struct lsys_cmd far *DrawTransform(char far *s)
  792. {
  793.   struct lsys_cmd far *ret;
  794.   struct lsys_cmd far *doub;
  795.   int max = 10;
  796.   int n = 0;
  797.   void (*f)(long);
  798.   long num;
  799.  
  800.   void (*plus)(long) = (ispow2(maxangle)) ? lsys_doplus_pow2 : lsys_doplus;
  801.   void (*minus)(long) = (ispow2(maxangle)) ? lsys_dominus_pow2 : lsys_dominus;
  802.   void (*pipe)(long) = (ispow2(maxangle)) ? lsys_dopipe_pow2 : lsys_dopipe;
  803.  
  804.   void (*slash)(long) =  (cpu == 386) ? lsys_doslash_386 : lsys_doslash;
  805.   void (*bslash)(long) = (cpu == 386) ? lsys_dobslash_386 : lsys_dobslash;
  806.   void (*at)(long) =     (cpu == 386) ? lsys_doat_386 : lsys_doat;
  807.   void (*drawg)(long) =  (cpu == 386) ? lsys_dodrawg_386 : lsys_dodrawg;
  808.  
  809.   ret = (struct lsys_cmd far *) farmemalloc((long) max * sizeof(struct lsys_cmd));
  810.   if (ret == NULL) {
  811.        stackoflow = 1;
  812.        return NULL;
  813.        }
  814.   while (*s) {
  815.     f = NULL;
  816.     num = 0;
  817.     ret[n].ch = *s;
  818.     switch (*s) {
  819.       case '+': f = plus;            break;
  820.       case '-': f = minus;           break;
  821.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  822.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  823.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  824.       case '|': f = pipe;            break;
  825.       case '!': f = lsys_dobang;     break;
  826.       case 'd': f = lsys_dodrawd;    break;
  827.       case 'm': f = lsys_dodrawm;    break;
  828.       case 'g': f = drawg;           break;
  829.       case 'f': f = lsys_dodrawf;    break;
  830.       case 'c': f = lsys_dodrawc;    num = getnumber(&s);    break;
  831.       case '<': f = lsys_dodrawlt;   num = getnumber(&s);    break;
  832.       case '>': f = lsys_dodrawgt;   num = getnumber(&s);    break;
  833.       case '[': num = 1;        break;
  834.       case ']': num = 2;        break;
  835.       default:
  836.     num = 3;
  837.     break;
  838.     }
  839.     ret[n].f = f;
  840.     ret[n].n = num;
  841.     if (++n == max) {
  842.       doub = (struct lsys_cmd far *) farmemalloc((long) max*2*sizeof(struct lsys_cmd));
  843.       if (doub == NULL) {
  844.            farmemfree(ret);
  845.            stackoflow = 1;
  846.            return NULL;
  847.            }
  848.       far_memcpy(doub, ret, max*sizeof(struct lsys_cmd));
  849.       farmemfree(ret);
  850.       ret = doub;
  851.       max <<= 1;
  852.     }
  853.     s++;
  854.   }
  855.   ret[n].ch = 0;
  856.   ret[n].f = NULL;
  857.   ret[n].n = 0;
  858.   n++;
  859.  
  860.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  861.   if (doub == NULL) {
  862.        farmemfree(ret);
  863.        stackoflow = 1;
  864.        return NULL;
  865.        }
  866.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  867.   farmemfree(ret);
  868.   return doub;
  869. }
  870.  
  871. static void free_lcmds()
  872. {
  873.   struct lsys_cmd far **sc = rules2;
  874.  
  875.   while (*sc)
  876.     farmemfree(*sc++);
  877. }
  878.  
  879.